use crate::AuthHeader;
use crate::handlers::posts::NewPost;
use crate::utils::jwt::{generate_token, validate_token};
use axum::http::HeaderMap;
use axum::{
    Extension, Json,
    extract::{Path, State},
    http::StatusCode,
};
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
use sqlx_core::sqlite::SqlitePool;
use tracing::debug;

#[derive(Serialize, Deserialize)]
pub struct NewUser {
    username: String,
    password: String,
    email: String,
}

#[derive(Serialize, Deserialize)]
pub struct LoginUser {
    username: String,
    password: String,
}

#[derive(Serialize, Deserialize, sqlx::FromRow, Debug)]
pub struct User {
    id: i32,
    username: String,
    password: String,
    email: String,
}

pub async fn validateUser(
    // 从全局路由状态获取数据库连接池
    State(pool): State<SqlitePool>,
    Extension(auth): Extension<AuthHeader>,
) -> Result<Json<User>, (StatusCode, String)> {
    debug!("get user profile which id is {}", auth.id);

    let result = sqlx::query_as("SELECT * FROM users WHERE id = $1")
        .bind(auth.id)
        .fetch_one(&pool)
        .await
        .map_err(|err| match err {
            sqlx::Error::RowNotFound => (StatusCode::NOT_FOUND, format!("Error is: {}", err)),
            _ => (
                StatusCode::INTERNAL_SERVER_ERROR,
                format!("Error is: {}", err),
            ),
        })?;

    // 经过中间件校验了header, 成功就进入这个接口, 返回user信息
    Ok(Json(result))
}

pub async fn login(
    // 从全局路由状态获取数据库连接池
    State(pool): State<SqlitePool>,
    Json(user): Json<LoginUser>,
) -> Result<Json<Value>, (StatusCode, String)> {
    let result =
        sqlx::query_as::<_, User>("SELECT * FROM users WHERE username = $1 and password = $2")
            .bind(&user.username)
            .bind(&user.password)
            .fetch_one(&pool)
            .await
            .map_err(|err| match err {
                sqlx::Error::RowNotFound => (StatusCode::NOT_FOUND, format!("Error is: {}", err)),
                _ => (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    format!("Error is: {}", err),
                ),
            })?;

    debug!("user: {result:?}");

    Ok(Json(json!({
        "token": generate_token(&result.id.to_string()).unwrap(),
        "userId": result.id,
    })))
}

pub async fn register(
    // 从全局路由状态获取数据库连接池
    State(pool): State<SqlitePool>,
    Json(user): Json<NewUser>,
) -> Result<Json<Value>, (StatusCode, String)> {
    let resp = sqlx::query("INSERT INTO users (username, password, email) values ($1, $2, $3)")
        // 填充占位符
        .bind(&user.username)
        .bind(&user.password)
        .bind(&user.email)
        .execute(&pool)
        .await
        .map_err(|err| {
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                format!("Error is: {}", err),
            )
        })?;
    Ok(Json(json!(user)))
}
